package com.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.system.constant.HTTPStatus;
import com.system.entity.*;
import com.system.mapper.PermissionMapper;
import com.system.mapper.RolePermissionMapper;
import com.system.response.Result;
import com.system.response.permission.PermissionDtoResponse;
import com.system.service.PermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.system.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.*;

/**
 * <p>
 * 权限表 服务实现类
 * </p>
 *
 * @author zfc
 * @since 2023-04-20
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public Result all() {
        List<Permission> info = permissionMapper.selectList(
                new LambdaQueryWrapper<Permission>()
                        .eq(Permission::getIsDelete, 0)
        );

        return new Result().setCode(HTTPStatus.SUCCESS).setData(info);
    }

    @Override
    public Set<String> selectAllPermissionKeyByRoleName(Set<String> roleName) {
        return permissionMapper.selectAllPermissionKeyByRoleName(roleName);
    }

    @Override
    public Result limitPermission(PermissionDtoResponse permissionDto) {
        if (permissionDto.getPageSize()==null || permissionDto.getPageSize()<0) permissionDto.setPageSize(1);
        if (permissionDto.getPageNum()==null || permissionDto.getPageNum()<10) permissionDto.setPageNum(10);
        PageHelper.startPage(permissionDto.getPageSize(), permissionDto.getPageNum());
        List<Permission> roleList = permissionMapper.selectList(
                new LambdaQueryWrapper<Permission>()
                        .eq(!StringUtils.isNull(permissionDto.getDelete()), Permission::getIsDelete, permissionDto.getDelete())
                        .like(!StringUtils.isNull(permissionDto.getKey()), Permission::getPermissionKey, permissionDto.getKey())
                        .orderByAsc(Permission::getPermissionSort)
        );
        PageInfo<Permission> info = new PageInfo<>(roleList);
        Integer count = permissionMapper.selectCount(
                new LambdaQueryWrapper<Permission>()
                        .eq(!StringUtils.isNull(permissionDto.getDelete()), Permission::getIsDelete, permissionDto.getDelete())
                        .like(!StringUtils.isNull(permissionDto.getKey()), Permission::getPermissionKey, permissionDto.getKey())
        );
        info.setSize(count);
        return new Result().setCode(HTTPStatus.SUCCESS).setData(info);
    }

    @Override
    public boolean addPerssion(Permission permission) {
        return permissionMapper.insert(permission) > 0;
    }

    @Override
    public Permission selectPermission(Integer id) {
        return permissionMapper.selectById(id);
    }

    @Override
    public boolean updatePerssion(Permission permission) {
        return permissionMapper.updateById(permission) > 0;
    }

    @Transactional(rollbackFor = Exception.class, timeout = 1000 * 60)
    @Override
    public boolean batchAdditionPermission(List<Permission> list) {
        boolean insert = this.saveBatch(list);
        return insert;
    }

    @Override
    public Result batchUpdatePermissionStatus(Integer[] ids, Integer isDelete) {

        Integer idsCount = permissionMapper.selectCount(
                new LambdaQueryWrapper<Permission>()
                        .in(Permission::getId, ids)
        );
        if (idsCount != ids.length) return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("存在权限不存在！");
        for (Integer id : ids) {
            //1、权限被角色绑定不能删除
            RolePermission newRp = new RolePermission();
            newRp.setPermissionId(id);
            boolean roleBoundPermission = this.checkRoleBoundPermission(newRp);
            if (roleBoundPermission){
                return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("权限中存在被使用【角色】关联，不能停用！");
            }
        }
        Collection<Permission> collection = new HashSet<>();
        for (Integer id : ids) {
            Permission permission = new Permission();
            permission.setId(id);
            permission.setIsDelete(isDelete);
            collection.add(permission);
        }
        boolean b = this.updateBatchById(collection, 100);

        String statusStr = isDelete == 0 ? "恢复":"停用";
        if (b) {
            return new Result().setCode(HTTPStatus.SUCCESS).setMessage(statusStr+"成功。");
        } else {
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage(statusStr+"失败，请联系管理员！");
        }
    }

    @Override
    public boolean batchDeletePermission(Integer[] ids) {
        Collection<Integer> collection = new HashSet<>();
        for (Integer id : ids) {
            collection.add(id);
        }
        return this.removeByIds(collection);
    }

    @Override
    public boolean checkPermissionUnique(Permission permission) {
        Permission newPermission = new Permission();
        newPermission.setId(permission.getId());
        newPermission.setPermissionKey(permission.getPermissionKey());

        if (!StringUtils.isNull(newPermission.getPermissionKey())) {
            newPermission.setId(null);
        }

        Permission selectOne = permissionMapper.selectOne(
                new LambdaQueryWrapper<Permission>()
                        .eq(!StringUtils.isNull(newPermission.getId()), Permission::getId, newPermission.getId())
                        .eq(!StringUtils.isNull(newPermission.getPermissionKey()), Permission::getPermissionKey, newPermission.getPermissionKey())
        );
        return !StringUtils.isNull(selectOne);
    }

    @Override
    public boolean checkPermissionKeyIsOneself(Permission permission) {
        Permission permission1 = permissionMapper.selectById(permission.getId());

        //如果修改的权限key 等于 没有修改的权限key
        if (!permission.getPermissionKey().equals(permission1.getPermissionKey())) {
            return true;
        }
        return false;
    }

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Override
    public List<Permission> queryRolesBoundPermission(Integer roleId) {
        List<RolePermission> rolePermissionList = rolePermissionMapper.selectList(
                new LambdaQueryWrapper<RolePermission>()
                        .eq(RolePermission::getRoleId, roleId)
        );
        //未绑定权限
        if (rolePermissionList.size() == 0) return null;

        Integer[] permissionIds = new Integer[rolePermissionList.size()];
        for (int i = 0; i < rolePermissionList.size(); i++) {
            permissionIds[i] = rolePermissionList.get(i).getPermissionId();
        }
        List<Permission> permissionList = permissionMapper.selectList(
                new LambdaQueryWrapper<Permission>()
                        .in(Permission::getId, permissionIds)
                        .eq(Permission::getIsDelete, 0)
                        .orderByAsc(Permission::getPermissionSort)
        );
        return permissionList;
    }

    @Override
    public boolean roleBoundPermission(Integer roleId, Integer[] permissionIds) {
        for (Integer permissionId : permissionIds) {
            RolePermission rp = new RolePermission();
            rp.setRoleId(roleId);
            rp.setPermissionId(permissionId);
            int insert = rolePermissionMapper.insert(rp);
            if (insert <= 0) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean checkRoleBoundPermissionUnique(Integer roleId, Integer[] permissionIds) {
        List<RolePermission> rolePermissionList = rolePermissionMapper.selectList(
                new LambdaQueryWrapper<RolePermission>()
                        .in(RolePermission::getPermissionId, permissionIds)
        );
        return rolePermissionList.size() == 0;
    }

    @Override
    public boolean batchDeleteRoleBoundPermission(Integer roleId, Integer[] permissionIds) {
        for (Integer permissionId : permissionIds) {
            int delete = rolePermissionMapper.delete(
                    new LambdaQueryWrapper<RolePermission>()
                            .eq(RolePermission::getRoleId, roleId)
                            .eq(RolePermission::getPermissionId, permissionId)
            );
            if (delete <= 0) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean deleteRoleBoundPermissionById(Integer roleId) {
        return rolePermissionMapper.delete(
                new LambdaQueryWrapper<RolePermission>()
                        .eq(RolePermission::getRoleId, roleId)
        ) > 0;
    }

    @Override
    public boolean checkRoleBoundPermission(RolePermission rp) {
        List<RolePermission> rolePermissionList = rolePermissionMapper.selectList(
                new LambdaQueryWrapper<RolePermission>()
                        .eq(!StringUtils.isNull(rp.getRoleId()), RolePermission::getRoleId, rp.getRoleId())
                        .eq(!StringUtils.isNull(rp.getPermissionId()), RolePermission::getPermissionId, rp.getPermissionId())
        );
        return rolePermissionList.size() > 0;
    }
}
